﻿using System;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace EnterpriseLibraryExtensions.Unity.ServiceModel
{
    /// <summary>
    /// The Unity attribute turns on instantiation of a WCF service by using Unity
    /// and the Unity container specified. Omitting any parameters, instantiates
    /// the service using the default container specified in the configuration file.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class)]
    public sealed class UnityAttribute : Attribute, IServiceBehavior
    {
        /// <summary>
        /// The name of the serviceDescription parameter.
        /// </summary>
        internal const string ServiceDescriptionParameter = "serviceDescription";

        /// <summary>
        /// Initializes a new instance of the <see cref="UnityAttribute"/> class.
        /// Initializes default values for the auto properties.
        /// </summary>
        public UnityAttribute()
        {
            this.ContainerName = string.Empty;
            this.UseGlobalContainer = false;
        }

        /// <summary>
        /// Gets or sets the name of the Unity container to load from configuration.
        /// </summary>
        public string ContainerName { get; set; }

        /// <summary>
        /// Gets or sets a value indicating whether the service should be instantiated using the globally
        /// registered Unity container or the container defined by ContainerName.
        /// </summary>
        public bool UseGlobalContainer { get; set; }

        /// <summary>
        /// Provides the ability to pass custom data to binding elements to support the contract implementation.
        /// </summary>
        /// <param name="serviceDescription">The service description of the service.</param>
        /// <param name="serviceHostBase">The host of the service.</param>
        /// <param name="endpoints">The service endpoints.</param>
        /// <param name="bindingParameters">Custom objects to which binding elements have access.</param>
        public void AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        /// <summary>
        /// Provides the ability to change run-time property values or insert custom extension objects such as error handlers, message or parameter interceptors, security extensions, and other custom extension objects.
        /// </summary>
        /// <param name="serviceDescription">The service description.</param>
        /// <param name="serviceHostBase">The host that is currently being built.</param>
        public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
            if (serviceDescription == null)
            {
                throw new ArgumentNullException(ServiceDescriptionParameter);
            }

            var serviceBehavior = this.UseGlobalContainer ? new UnityServiceBehavior(true) : new UnityServiceBehavior(this.ContainerName);

            serviceDescription.Behaviors.Add(serviceBehavior);
        }

        /// <summary>
        /// Provides the ability to inspect the service host and the service description to confirm that the service can run successfully.
        /// </summary>
        /// <param name="serviceDescription">The service description.</param>
        /// <param name="serviceHostBase">The service host that is currently being constructed.</param>
        public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
        {
        }
    }
}
